#ifndef VL_VEC_HPP
#define VL_VEC_HPP

#include <cmath>
//#include "angle.h"
//#include "math_func.h"

namespace vl
{

template<typename T>
struct basic_vec
{
	typedef T manip_t;
	typedef T coord_type;
	
	basic_vec()
	: x(T(0)), y(T(0))
	{
		
	}
	
	template<class T2>
	explicit basic_vec(basic_vec<T2> const& b)
	: x(static_cast<T>(b.x)), y(static_cast<T>(b.y))
	{
		
	}
		
	basic_vec(basic_vec const& a, basic_vec const& b)
	: x(b.x - a.x), y(b.y - a.y)
	{
		
	}

	basic_vec(T const& x_, T const& y_)
	: x(x_) , y(y_)
	{
	}
	
	template<class T2>
	basic_vec(T2 const& x, T2 const& y)
	: x(x), y(y)
	{
		
	}
	
	void zero()
	{
		x = T(0);
		y = T(0);
	}
	
	basic_vec operator - (basic_vec const &A) const
	{
		return basic_vec(x - A.x, y - A.y);
	}
	
	basic_vec operator + (basic_vec const &A) const
	{
		return basic_vec(x + A.x, y + A.y);
	}
	
	friend basic_vec operator * (T const& A, basic_vec const& B)
	{
		return basic_vec(A * B.x, A * B.y);
	}
	
	basic_vec operator * (T const& A) const
	{
		return basic_vec(A * x, A * y);
	}
	
	basic_vec operator / (T const& A) const
	{
		return basic_vec(x / A, y / A);
	}
	
	basic_vec& operator += (basic_vec const& A)
	{
		x += A.x;
		y += A.y;
		return *this;
	}
	
	basic_vec& operator -= (basic_vec const& A)
	{
		x -= A.x;
		y -= A.y;
		return *this;
	}
	
	basic_vec& operator *= (T const& A)
	{
		x *= A;
		y *= A;
		return *this;
	}
	
	basic_vec& operator /= (T const& A)
	{
		x /= A;
		y /= A;
		return *this;
	}
	
	basic_vec operator - () const
	{
		return basic_vec(-x, -y);
	}
	
	basic_vec half() const
	{
		return basic_vec(x / T(2), y / T(2));
	}
	
	T dot(basic_vec const& A) const
	{
		return x * A.x + y * A.y;
	}
	
	T perp_dot(basic_vec const& A) const
	{
		return x * A.y - y * A.x;
	}
		
	basic_vec perp() const
	{
		return basic_vec(-y, x);
	}
	
	basic_vec rotate(basic_vec const& A) const
	{
		return basic_vec(x * A.x - y * A.y, x * A.y + y * A.x);
	}
	
	basic_vec unrotate(basic_vec const& A) const
	{
		return basic_vec(x * A.x + y * A.y, y * A.x - x * A.y);
	}
	
	double length() const
	{
		return std::sqrt(double(x*x + y*y));
	}
	
	basic_vec normal() const
	{
		double invLength = 1.0 / length();
		return basic_vec(T(x*invLength), T(y*invLength));
	}
	
	T length_sqr() const
	{
		return x*x + y*y;
	}
	
	bool operator==(basic_vec const& b) const
	{
		return x == b.x && y == b.y;
	}
	
	bool operator!=(basic_vec const& b) const
	{
		return !(*this == b);
	}
		
	T x;
	T y;
	
};

typedef basic_vec<float> vec;
typedef basic_vec<int> ivec;

}

#endif // VL_VEC_HPP
